<?php
/**
 * 数据库读写分离管理类
 * 该类 结合分库分表使用，不支持单独使用
 */
 
class CDbConnectionMasterSlave extends CDbConnection {
	public $driverMap = array(
		'mysql'=>'CMysqlSchemaExt',
	);
	
	/**
	 * @see CDbConnection->autoConnect
	 */
	public $autoConnect = false;
	
	/**
	 * PDO::ATTR_TIMEOUT
	 */
	public $pdoTimeout = 2;
	
	/**
	 * 是否启用从库连接
	 * @var bool $enableSlave 
	 */
	public $enableSlave = true;
	
	/**
	 * 数据库会话最大等待时间，超过此时间未活动则该数据库连接超时
	 */
	public $waitSession = 15;
	
	/**
	 * PDO连接的最后活动时间，用于判断此连接是否超时
	 */
	private static $_lastActivityTime = array();

	/**
	 * @see parent::createPdoInstance
	 */
	protected function createPdoInstance() {
		$this->setAttribute(PDO::ATTR_TIMEOUT, $this->pdoTimeout);
		return parent::createPdoInstance();
	}
	
	/**
	 * 却掉 pdo->quote, 直接使用 addcslashes
	 * see parent::quoteValue
	 */
	public function quoteValue($str) {
		if(is_int($str) || is_float($str))
			return $str;

		return "'" . addcslashes(str_replace("'", "''", $str), "\000\n\r\\\032") . "'";
	}
	
	/**
	 * 创建一个CDbCommand对象执行SQL语句语句.
	 * 读写判断，强制主库等
	 * 
	 * @param mixed $sql
	 * @return CDbCommand
	 */
	public function createCommand($sql = null) {
		return new CDbCommandExt($this, $sql);
	}
	
	/**
	 * 激活数据库连接, 
	 * 根据最后活动时间 和 waitSession 判断此连接是否过期，若过期则重连
	 */
	public function active() {
		$hash = md5($this->connectionString);
		$time = time();
		$now = $time - $this->waitSession + 2;
		
		if(!isset(self::$_lastActivityTime[$hash]) || self::$_lastActivityTime[$hash] < $now) {
			Yii::trace("Active: {$this->connectionString}", __METHOD__.':'.__LINE__);
			$this->setActive(false);
			$this->setActive(true);
		}
		
		self::$_lastActivityTime[$hash] = $time;
	}

	/**
	 * 获取一个从库链接.
	 * @return CDbConnection
	 */
	public function getSlave() {
		$slave = CDbManager::conn()->getDbConnection(false);
		if(!$slave) throw new Exception('No slave configuration is available! ('.__METHOD__.':'.__LINE__.')');

		return $slave;
	}
}
